/***************************************************
    该demo主要是使用AT命令控制播放音频,录制格式为WAV
	AT命令格式：AT+xxx.wav
***************************************************/
#include "osal/string.h"
#include "custom_mem/custom_mem.h"
#include "stream_frame.h"
#include "osal/task.h"
#include "osal_file.h"

#define AUDIO_LEN  (1024)
char audio_filePath[10];
void *audio_fp = NULL;

typedef struct _riff_chunk {
	uint8  ChunkID[4];
	uint32 ChunkSize;
	uint8  Format[4];
} TYPE_RIFF_CHUNK;
typedef struct _fmt_chunk {
	uint8  FmtID[4];
	uint32 FmtSize;
	uint16 FmtTag;
	uint16 FmtChannels;
	uint32 SampleRate;
	uint32 ByteRate;
	uint16 BlockAlign;
	uint16 BitsPerSample;
} TYPE_FMT_CHUNK;
typedef struct _data_chunk {
	uint8  DataID[4];
	uint32 DataSize;
} TYPE_DATA_CHUNK;
typedef struct _wave_head {
	TYPE_RIFF_CHUNK  riff_chunk;
	TYPE_FMT_CHUNK   fmt_chunk;
	TYPE_DATA_CHUNK  data_chunk;
} TYPE_WAVE_HEAD;

TYPE_WAVE_HEAD *wave_head = NULL;
uint32 audio_data_len;
struct os_task at_play_audio_task;


static uint32_t get_sound_data_len(void *data)
{
	return AUDIO_LEN;
}
static stream_ops_func stream_sound_ops = 
{
	.get_data_len = get_sound_data_len,
};

int at_play_audio_thread(void *d);
int32 demon_atcmd_play_audio(const char *cmd, char *argv[], uint32 argc)
{
	if(argc < 1)
    {
        os_printf("%s argc too small:%d,enter the path\n",__FUNCTION__,argc);
        return 0;
    }

	if(argv[0])
	{
		memset(audio_filePath,0,sizeof(audio_filePath));
		memcpy(audio_filePath,argv[0],strlen(argv[0]));
		os_printf("audio path:%s\n",audio_filePath);
		audio_fp = osal_fopen(audio_filePath,"rb");
		if(!audio_fp)
		{
			os_printf("\nopen audio file err");
			return 0;
		}
		wave_head = (TYPE_WAVE_HEAD*)custom_malloc(sizeof(TYPE_WAVE_HEAD));
		if(!wave_head)
			return 0;
		osal_fread(wave_head,1,sizeof(TYPE_WAVE_HEAD),audio_fp);
		audio_data_len = wave_head->data_chunk.DataSize;

		os_printf("SampleRate:%d FmtChannels:%d BitsPerSample:%d\r\n",
			wave_head->fmt_chunk.SampleRate,wave_head->fmt_chunk.FmtChannels,wave_head->fmt_chunk.BitsPerSample);
		/*当前只支持单声道、16位宽深度的音频格式,采样率与dac初始化时一致*/
		if((wave_head->fmt_chunk.FmtChannels != 1) || (wave_head->fmt_chunk.BitsPerSample != 16) || (wave_head->fmt_chunk.SampleRate != 8000))
		{
			os_printf("\nAudio format is not supported");   
			custom_free(wave_head);
			return 0;
		}		
		OS_TASK_INIT("at_play_audio", &at_play_audio_task, at_play_audio_thread, (uint32)audio_fp, OS_TASK_PRIORITY_NORMAL, 1024);
	}
}

static int opcode_func(stream *s,void *priv,int opcode)
{
	static uint8 *audio_buf = NULL;
	int res = 0;
	switch(opcode)
	{
		case STREAM_OPEN_ENTER:
		break;
		case STREAM_OPEN_EXIT:
		{			
			audio_buf = os_malloc(4 * AUDIO_LEN);
			if(audio_buf)
			{
				stream_data_dis_mem(s,4);
			}
			streamSrc_bind_streamDest(s,R_SPEAKER);			
		}
		break;
		case STREAM_OPEN_FAIL:
		break;

		case STREAM_FILTER_DATA:
		break;

		case STREAM_DATA_DIS:
		{
			struct data_structure *data = (struct data_structure *)priv;
			int data_num = (int)data->priv;
			data->ops = &stream_sound_ops;
			data->data = audio_buf + (data_num)*AUDIO_LEN;
		}
		break;

		case STREAM_DATA_FREE:
			//_os_printf("%s:%d\n",__FUNCTION__,__LINE__);
		break;


		//数据发送完成,可以选择唤醒对应的任务
		case STREAM_RECV_DATA_FINISH:
		break;

		default:
			//默认都返回成功
		break;
	}
	return res;	
}
uint8 *wav_fp = NULL;
int at_play_audio_thread(void *d)
{
	int readLen = 0;
	uint32 read_total_len = 0;
	struct data_structure *data = NULL;
	int former_dac_priv = 0;

	FIL *fp = (FIL*)d;	
	stream *src = open_stream_available("file_audio", 4, 0, opcode_func,NULL);

	if(!src)
	{
		osal_fclose(fp);
		custom_free(wave_head);
		os_printf("\nopen stream err");
		return 0;
	}
	former_dac_priv = get_audio_dac_set_filter_type();
	audio_dac_set_filter_type(SOUND_FILE);
	while(read_total_len < audio_data_len)
	{
		data = get_src_data_f(src);
		if(data)
		{
			wav_fp = get_stream_real_data(data);
			readLen = osal_fread(wav_fp, 1, AUDIO_LEN, fp);
			if(readLen > 0)
			{
				read_total_len += readLen;
				data->type = SET_DATA_TYPE(SOUND, SOUND_FILE);
				send_data_to_stream(data);
			}
			if(readLen <= 0 )
			{
				os_printf("\nread audio data err");
				break;
			}
		}
	}
	os_printf("\nplay wav end");
	audio_dac_set_filter_type(former_dac_priv);
	osal_fclose(fp);
	custom_free(wave_head);
	close_stream(src);
	src = NULL;
	return 0;
}